home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / TinyGL / ami / content / ad709 / tinygl / src / vertex.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-15  |  8.6 KB  |  366 lines

  1. /*$T vertex.c GC 1.137 08/09/02 17:47:18 */
  2.  
  3. /*$6
  4.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  5.  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  6.  */
  7.  
  8. #include "zgl.h"
  9.  
  10. /* */
  11.  
  12. void glopNormal(GLContext *c, GLParam *p) {
  13.     V3    v;
  14.     /*~~*/
  15.  
  16.     v.X = p[1].f;
  17.     v.Y = p[2].f;
  18.     v.Z = p[3].f;
  19.  
  20.     c->current_normal.X = v.X;
  21.     c->current_normal.Y = v.Y;
  22.     c->current_normal.Z = v.Z;
  23.     c->current_normal.W = 0;
  24. }
  25.  
  26. /* */
  27. void glopTexCoord(GLContext *c, GLParam *p) {
  28.     c->current_tex_coord.X = p[1].f;
  29.     c->current_tex_coord.Y = p[2].f;
  30.     c->current_tex_coord.Z = p[3].f;
  31.     c->current_tex_coord.W = p[4].f;
  32. }
  33.  
  34. /* */
  35. void glopEdgeFlag(GLContext *c, GLParam *p) {
  36.     c->current_edge_flag = p[1].i;
  37. }
  38.  
  39. /* */
  40. void glopColor(GLContext *c, GLParam *p) {
  41.     c->current_color.X = p[1].f;
  42.     c->current_color.Y = p[2].f;
  43.     c->current_color.Z = p[3].f;
  44.     c->current_color.W = p[4].f;
  45.     c->longcurrent_color[0] = p[5].ui;
  46.     c->longcurrent_color[1] = p[6].ui;
  47.     c->longcurrent_color[2] = p[7].ui;
  48.  
  49.     if(c->color_material_enabled) {
  50.         GLParam q[7];
  51.         q[0].op = OP_Material;
  52.         q[1].i = c->current_color_material_mode;
  53.         q[2].i = c->current_color_material_type;
  54.         q[3].f = p[1].f;
  55.         q[4].f = p[2].f;
  56.         q[5].f = p[3].f;
  57.         q[6].f = p[4].f;
  58.         glopMaterial(c, q);
  59.     }
  60. }
  61.  
  62. /* */
  63. void gl_eval_viewport(GLContext *c) {
  64.     GLViewport    *v;
  65.     float        zsize = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS));
  66.  
  67.     v = &c->viewport;
  68.  
  69.     v->trans.X = ((v->xsize - 0.5) / 2.0) + v->xmin;
  70.     v->trans.Y = ((v->ysize - 0.5) / 2.0) + v->ymin;
  71.     v->trans.Z = ((zsize - 0.5) / 2.0) + ((1 << ZB_POINT_Z_FRAC_BITS)) / 2;
  72.  
  73.     v->scale.X = (v->xsize - 0.5) / 2.0;
  74.     v->scale.Y = -(v->ysize - 0.5) / 2.0;
  75.     v->scale.Z = -((zsize - 0.5) / 2.0);
  76. }
  77.  
  78. /* */
  79. void glopBegin(GLContext *c, GLParam *p) {
  80.     int type;
  81.     M4    tmp;
  82.  
  83.     assert(c->in_begin == 0);
  84.  
  85.     type = p[1].i;
  86.     c->begin_type = type;
  87.     c->in_begin = 1;
  88.     c->vertex_n = 0;
  89.     c->vertex_cnt = 0;
  90.  
  91.     if(c->matrix_model_projection_updated) {
  92.         if(c->lighting_enabled) {
  93.             /* precompute inverse modelview */
  94.             gl_M4_Inv(&tmp, c->matrix_stack_ptr[0]);
  95.             gl_M4_Transpose(&c->matrix_model_view_inv, &tmp);
  96.         }
  97.         else {
  98.             float    *m = &c->matrix_model_projection.m[0][0];
  99.  
  100.             /* precompute projection matrix */
  101.             gl_M4_Mul(&c->matrix_model_projection, c->matrix_stack_ptr[1], c->matrix_stack_ptr[0]);
  102.  
  103.             /* test to accelerate computation */
  104.             c->matrix_model_projection_no_w_transform = 0;
  105.             if(m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) {
  106.                 c->matrix_model_projection_no_w_transform = 1;
  107.             }
  108.         }
  109.  
  110.         /* test if the texture matrix is not Identity */
  111.         c->apply_texture_matrix = !gl_M4_IsId(c->matrix_stack_ptr[2]);
  112.  
  113.         c->matrix_model_projection_updated = 0;
  114.     }
  115.  
  116.     /* viewport */
  117.     if(c->viewport.updated) {
  118.         gl_eval_viewport(c);
  119.         c->viewport.updated = 0;
  120.     }
  121.  
  122.     /* triangle drawing functions */
  123.     if(c->render_mode == GL_SELECT) {
  124.         c->draw_triangle_front = gl_draw_triangle_select;
  125.         c->draw_triangle_back = gl_draw_triangle_select;
  126.     }
  127.     else {
  128.         switch(c->polygon_mode_front) {
  129.         case GL_POINT:    c->draw_triangle_front = gl_draw_triangle_point; break;
  130.         case GL_LINE:    c->draw_triangle_front = gl_draw_triangle_line; break;
  131.         default:        c->draw_triangle_front = gl_draw_triangle_fill; break;
  132.         }
  133.  
  134.         switch(c->polygon_mode_back) {
  135.         case GL_POINT:    c->draw_triangle_back = gl_draw_triangle_point; break;
  136.         case GL_LINE:    c->draw_triangle_back = gl_draw_triangle_line; break;
  137.         default:        c->draw_triangle_back = gl_draw_triangle_fill; break;
  138.         }
  139.     }
  140. }
  141.  
  142. /*
  143.  * coords, tranformation , clip code and projection £
  144.  * TODO:: handle all cases
  145.  */
  146. static inline void gl_vertex_transform(GLContext *c, GLVertex *v) {
  147.     float    *m;
  148.     V4        *n;
  149.  
  150.     if(c->lighting_enabled) {
  151.         /* eye coordinates needed for lighting */
  152.         m = &c->matrix_stack_ptr[0]->m[0][0];
  153.         v->ec.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]);
  154.         v->ec.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]);
  155.         v->ec.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]);
  156.         v->ec.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]);
  157.  
  158.         /* projection coordinates */
  159.         m = &c->matrix_stack_ptr[1]->m[0][0];
  160.         v->pc.X = (v->ec.X * m[0] + v->ec.Y * m[1] + v->ec.Z * m[2] + v->ec.W * m[3]);
  161.         v->pc.Y = (v->ec.X * m[4] + v->ec.Y * m[5] + v->ec.Z * m[6] + v->ec.W * m[7]);
  162.         v->pc.Z = (v->ec.X * m[8] + v->ec.Y * m[9] + v->ec.Z * m[10] + v->ec.W * m[11]);
  163.         v->pc.W = (v->ec.X * m[12] + v->ec.Y * m[13] + v->ec.Z * m[14] + v->ec.W * m[15]);
  164.  
  165.         m = &c->matrix_model_view_inv.m[0][0];
  166.         n = &c->current_normal;
  167.  
  168.         v->normal.X = (n->X * m[0] + n->Y * m[1] + n->Z * m[2]);
  169.         v->normal.Y = (n->X * m[4] + n->Y * m[5] + n->Z * m[6]);
  170.         v->normal.Z = (n->X * m[8] + n->Y * m[9] + n->Z * m[10]);
  171.  
  172.         if(c->normalize_enabled) {
  173.             gl_V3_Norm(&v->normal);
  174.         }
  175.     }
  176.     else {
  177.         /*
  178.          * no eye coordinates needed, no normal £
  179.          * NOTE: W = 1 is assumed
  180.          */
  181.         m = &c->matrix_model_projection.m[0][0];
  182.  
  183.         v->pc.X = (v->coord.X * m[0] + v->coord.Y * m[1] + v->coord.Z * m[2] + m[3]);
  184.         v->pc.Y = (v->coord.X * m[4] + v->coord.Y * m[5] + v->coord.Z * m[6] + m[7]);
  185.         v->pc.Z = (v->coord.X * m[8] + v->coord.Y * m[9] + v->coord.Z * m[10] + m[11]);
  186.         if(c->matrix_model_projection_no_w_transform) {
  187.             v->pc.W = m[15];
  188.         }
  189.         else {
  190.             v->pc.W = (v->coord.X * m[12] + v->coord.Y * m[13] + v->coord.Z * m[14] + m[15]);
  191.         }
  192.     }
  193.  
  194.     v->clip_code = gl_clipcode(v->pc.X, v->pc.Y, v->pc.Z, v->pc.W);
  195. }
  196.  
  197. /* */
  198. void glopVertex(GLContext *c, GLParam *p) {
  199.     GLVertex    *v;
  200.     int            n, i, cnt;
  201.  
  202.     assert(c->in_begin != 0);
  203.  
  204.     n = c->vertex_n;
  205.     cnt = c->vertex_cnt;
  206.     cnt++;
  207.     c->vertex_cnt = cnt;
  208.  
  209.     /* quick fix to avoid crashes on large polygons */
  210.     if(n >= c->vertex_max) {
  211.         GLVertex    *newarray;
  212.         c->vertex_max <<= 1;    /* just double size */
  213.         newarray = malloc(sizeof(GLVertex) * c->vertex_max);
  214.         if(!newarray) {
  215.             gl_fatal_error("unable to allocate GLVertex array.\n");
  216.         }
  217.  
  218.         memcpy(newarray, c->vertex, n * sizeof(GLVertex));
  219.         free(c->vertex);
  220.         c->vertex = newarray;
  221.     }
  222.  
  223.     /* new vertex entry */
  224.     v = &c->vertex[n];
  225.     n++;
  226.  
  227.     v->coord.X = p[1].f;
  228.     v->coord.Y = p[2].f;
  229.     v->coord.Z = p[3].f;
  230.     v->coord.W = p[4].f;
  231.  
  232.     gl_vertex_transform(c, v);
  233.  
  234.     /* color */
  235.     if(c->lighting_enabled) {
  236.         gl_shade_vertex(c, v);
  237.     }
  238.     else {
  239.         v->color = c->current_color;
  240.     }
  241.  
  242.     /* tex coords */
  243.     if(c->texture_2d_enabled) {
  244.         if(c->apply_texture_matrix) {
  245.             gl_M4_MulV4(&v->tex_coord, c->matrix_stack_ptr[2], &c->current_tex_coord);
  246.         }
  247.         else {
  248.             v->tex_coord = c->current_tex_coord;
  249.         }
  250.     }
  251.  
  252.     /* precompute the mapping to the viewport */
  253.     if(v->clip_code == 0) {
  254.         gl_transform_to_viewport(c, v);
  255.     }
  256.  
  257.     /* edge flag */
  258.     v->edge_flag = c->current_edge_flag;
  259.  
  260.     switch(c->begin_type) {
  261.     case GL_POINTS:
  262.         gl_draw_point(c, &c->vertex[0]);
  263.         n = 0;
  264.         break;
  265.  
  266.     case GL_LINES:
  267.         if(n == 2) {
  268.             gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
  269.             n = 0;
  270.         }
  271.         break;
  272.     case GL_LINE_STRIP:
  273.     case GL_LINE_LOOP:
  274.         if(n == 1) {
  275.             c->vertex[2] = c->vertex[0];
  276.         }
  277.         else if(n == 2) {
  278.             gl_draw_line(c, &c->vertex[0], &c->vertex[1]);
  279.             c->vertex[0] = c->vertex[1];
  280.             n = 1;
  281.         }
  282.         break;
  283.  
  284.     case GL_TRIANGLES:
  285.         if(n == 3) {
  286.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  287.             n = 0;
  288.         }
  289.         break;
  290.     case GL_TRIANGLE_STRIP:
  291.         if(cnt >= 3) {
  292.             if(n == 3) {
  293.                 n = 0;
  294.             }
  295.  
  296.             /* needed to respect triangle orientation */
  297.             switch(cnt & 1) {
  298.             case 0:
  299.                 gl_draw_triangle(c, &c->vertex[2], &c->vertex[1], &c->vertex[0]);
  300.                 break;
  301.             default:
  302.             case 1:
  303.                 gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  304.                 break;
  305.             }
  306.         }
  307.         break;
  308.     case GL_TRIANGLE_FAN:
  309.         if(n == 3) {
  310.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  311.             c->vertex[1] = c->vertex[2];
  312.             n = 2;
  313.         }
  314.         break;
  315.  
  316.     case GL_QUADS:
  317.         if(n == 4) {
  318.             c->vertex[2].edge_flag = 0;
  319.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  320.             c->vertex[2].edge_flag = 1;
  321.             c->vertex[0].edge_flag = 0;
  322.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[2], &c->vertex[3]);
  323.             n = 0;
  324.         }
  325.         break;
  326.  
  327.     case GL_QUAD_STRIP:
  328.         if(n == 4) {
  329.             gl_draw_triangle(c, &c->vertex[0], &c->vertex[1], &c->vertex[2]);
  330.             gl_draw_triangle(c, &c->vertex[1], &c->vertex[3], &c->vertex[2]);
  331.             for(i = 0; i < 2; i++) {
  332.                 c->vertex[i] = c->vertex[i + 2];
  333.             }
  334.  
  335.             n = 2;
  336.         }
  337.         break;
  338.     case GL_POLYGON:
  339.         break;
  340.     default:
  341.         gl_fatal_error("glBegin: type %x not handled\n", c->begin_type);
  342.     }
  343.  
  344.     c->vertex_n = n;
  345. }
  346.  
  347. /* */
  348. void glopEnd(GLContext *c, GLParam *param) {
  349.     assert(c->in_begin == 1);
  350.  
  351.     if(c->begin_type == GL_LINE_LOOP) {
  352.         if(c->vertex_cnt >= 3) {
  353.             gl_draw_line(c, &c->vertex[0], &c->vertex[2]);
  354.         }
  355.     }
  356.     else if(c->begin_type == GL_POLYGON) {
  357.         int i = c->vertex_cnt;
  358.         while(i >= 3) {
  359.             i--;
  360.             gl_draw_triangle(c, &c->vertex[i], &c->vertex[0], &c->vertex[i - 1]);
  361.         }
  362.     }
  363.  
  364.     c->in_begin = 0;
  365. }
  366.